프로그램()
{
입력을 받는다.
정보를 조금 처리한다.
조금 출력한다.
입력을 또 받는다.
정보를 또 처리한다.
더 출력한다.
}
| Controller | 사용자의 입력을 받아 처리하고, Model과 상호작용하며, 적절한 View를 선택해 주는 역할 |
| Model | 프로그램이 사용될 영역에 따라서 처리해야 하는 논리들을 처리하는 부분입니다. 대개의 경우 Database에 내용을 넣고, 빼고, 바꾸고 하는 것이 Model에서 처리 |
| View | 프로그램의 외관을 책임지는 부분입니다. Model의 정보들을 받아서 화면에 그리는 역할 |

<?php
$bugsTable = Doctrine_Core::getTable('Bugs');
$bugsTable->find(1234);
$bug = new Bugs();
$bug->summary = "Crashes when I save";
$bug->save();
<?php
class CustomBugs extends BaseBugs
{
public function assignUser(Accounts $a)
{
$this->assigned_to = $a->account_id;
$this->save();
mail($a->email, "Assigned bug",
"You are now responsible for bug #{$this->bug_id}.");
}
}
<?php
$bugsTable = Doctrine_Core::getTable('Bugs');
$bugsTable->find(1234);
$bug = new Bugs();
$bug->summary = "Crashes when I save";
$bug->save();
<?php
class AdminController extends Zend_Controller_Action
{
public function assignAction()
{
$bugsTable = Doctrine_Core::getTable("Bugs");
$bug = $bugsTable->find($_POST["bug_id"]);
$bug->Products[] = $_POST["product_id"];
$bug->assigned_to = $_POST["user_assigned_to"];
$bug->save();
}
}
class BugController extends Zend_Controller_Action
{
public function enterAction()
{
$bug = new Bugs();
$bug->summary = $_POST["summary"];
$bug->description = $_POST["summary"];
$bug->status = "NEW";
$accountsTable = Doctrine_Core::getTable("Accounts");
$auth = Zend_Auth::getInstance();
if ($auth && $auth->hasIdentity()) {
$bug->reported_by = $auth->getIdentity();
}
$bug->save();
}
public function displayAction()
{
$bugsTable = Doctrine_Core::getTable("Bugs");
$this->view->bug = $bugsTable->find($_GET["bug_id"]);
$accountsTable = Doctrine_Core::getTable("Accounts");
$this->view->reportedBy = $accountsTable->find($bug->reported_by);
$this->view->assignedTo = $accountsTable->find($bug->assigned_to);
$this->view->verifiedBy = $accountsTable->find($bug->verified_by);
$productsTable = Doctrine_Core::getTable("Products");
$this->view->products = $bug->Products;
}
}
class SearchController extends Zend_Controller_Action
{
public function bugsAction()
{
$q = Doctrine_Query::create()
->from("Bugs b")
->join("b.Products p")
->where("b.status = ?", $_GET["status"])
->andWhere("MATCH(b.summary, b.description) AGAINST (?)", $_GET["search"]);
$this->view->searchResults = $q->fetchArray();
}
}

| 모델 테스트 | 모델을 액티브 레코드와 같은 클래스로 만들었기 때문에, 데이터 접근과 분리해 모델의 동작을 테스트할 수 없음. 모델을 테스트하려면, 실제 데이터베이스에 쿼리를 실행해야 하며, 이로 인해 모델테스트를 위하 준비작업과 정리 작업을 느리게 하고 에러 발생 가능성을 높임. |
| 뷰 테스트 | 뷰를 테스트한다는 말응 뷰를 HTML로 렌더링하고 결과를 파싱해 모델로부터 제공받은 동적 HTML 요소가 출력에 나타나는지 확인한다는 의미. |
| 컨트롤러 테스트 | 데이터 접근 객체인 모델로 인해 여러 컨트롤러에 동일한 코드가 반복해서 나타나게 되는데, 이 모든 것이 테스트되어야 하며, 이로 인해 비지니스 로직을 테스트하는 데 많은 설정 코드가 필요해지고, 테스트 실행도 느려짐 |
<?php
class BugReport
{
protected $bugsTable;
protected $accountsTable;
protected $productsTable;
public function __construct()
{
$this->bugsTable = Doctrine_Core::getTable("Bugs");
$this->accountsTable = Doctrine_Core::getTable("Accounts");
$this->productsTable = Doctrine_Core::getTable("Products");
}
public function create($summary, $description, $reportedBy)
{
$bug = new Bugs();
$bug->summary = $summary
$bug->description = $description
$bug->status = "NEW";
$bug->reported_by = $reportedBy;
$bug->save();
}
public function assignUser($bugId, $assignedTo)
{
$bug = $bugsTable->find($bugId);
$bug->assigned_to = $assignedTo"];
$bug->save();
}
public function get($bugId)
{
return $bugsTable->find($bugId);
}
public function search($status, $searchString)
{
$q = Doctrine_Query::create()
->from("Bugs b")
->join("b.Products p")
->where("b.status = ?", $status)
->andWhere("MATCH(b.summary, b.description) AGAINST (?)", $searchString]);
return $q->fetchArray();
}
}
class AdminController extends Zend_Controller_Action
{
public function assignAction()
{
$this->bugReport->assignUser(
$this->_getParam("bug"),
$this->_getParam("user"));
}
}
class BugController extends Zend_Controller_Action
{
public function enterAction()
{
$auth = Zend_Auth::getInstance();
if ($auth && $auth->hasIdentity()) {
$identity = $auth->getIdentity();
}
$this->bugReport->create(
$this->_getParam("summary"),
$this->_getParam("description"),
$identity);
}
public function displayAction()
{
$this->view->bug = $this->bugReport->get(
$this->_getParam("bug"));
}
}
class SearchController extends Zend_Controller_Action
{
public function bugsAction()
{
$this->view->searchResults = $this->bugReport->search(
$this->_getParam("status", "OPEN"),
$this->_getParam("search"));
}
}

테이블에서 모델을 분리하라.